import 'console_output.dart';
import 'log_entity.dart';
import 'pretty_printer.dart';
import 'log_printer.dart';
import 'log_output.dart';

class Logger {
  static Logger _instance = _getInstance();

  static Level level = Level.debug;

  final LogPrinter _printer; // 打印器，控制日志输出样式和堆栈信息等
  final LogOutput _output; // 输出器，控制日志输出位置和格式等.可以是控制台、文件、内存等
  final bool _loggable;


  Logger._internal({
    bool? loggable,
    LogPrinter? printer,
    LogOutput? output,
    Level? level,
  }):
    _loggable = loggable ?? true,
    _printer = printer ?? PrettyPrinter(),
    _output = output ?? ConsoleOutput()
    {
      _output.init();
      _printer.init();
    }

  static Logger init(bool loggable){
    return _getInstance(loggable: loggable);
  }
  //一个名为 _getInstance 的静态私有方法，用于创建并返回一个 Logger 类的单例实例。
  //它采用了单例模式（Singleton Pattern），
  //确保在整个应用生命周期中，Logger 实例只被创建一次或按需重新配置。返回值是 Logger 类型。
  // 该方法接受四个可选参数：
  // loggable: 一个布尔值，指示是否启用日志记录功能。如果为 null，则默认为 true。
  // printer: 一个 LogPrinter 对象，用于定义日志的打印格式。如果为 null，则使用默认的 PrettyPrinter。
  // output: 一个 LogOutput 对象，定义日志的输出目标（如控制台或文件）。如果为 null，则使用默认的 ConsoleOutput。
  // level: 一个 Level 枚举值，表示日志的级别（如 debug、info、error）。如果为 null，则使用默认的 Level.debug。
  // 方法内部，它通过传入的参数（或默认值）调用 Logger 类的私有构造函数 _internal 来创建 Logger 实例，
  //并将其赋值给静态变量 _instance。 最后，方法返回这个单例实例。
  static Logger getInstance({
    bool? loggable,
    LogPrinter? printer,
    LogOutput? output,
    Level? level,
  }) {
      _instance = Logger._internal(
      loggable: loggable ?? true,
      printer: printer ?? PrettyPrinter(),
      output: output ?? ConsoleOutput(),
      level: level ?? Level.debug,
    );
    return _instance;
  }

  static Logger _getInstance({
    bool? loggable,
    LogPrinter? printer,
    LogOutput? output,
    Level? level,
  }) {
      _instance = Logger._internal(
      loggable: loggable ?? true,
      printer: printer ?? PrettyPrinter(),
      output: output ?? ConsoleOutput(),
      level: level ?? Level.debug,
    );
    return _instance;
  }

  ///
  /// message: 日志内容
  /// tag: 日志标签
  /// level: 日志等级
  /// stackTrace: 堆栈信息.作用是： 获取调用日志的堆栈信息
  ///
  static void d(dynamic message, [String? tag, StackTrace? stackTrace]) {
    _instance.log(Level.debug, message, "D/PRETTY_LOGGER${tag==null?"":" [$tag] "}", stackTrace);
  }


  static void i(dynamic message, [String? tag, StackTrace? stackTrace]) {
    _instance.log(Level.info, message, "I/PRETTY_LOGGER${tag==null?"":" [$tag] "}", stackTrace);
  }

  static void e(dynamic message, [String? tag, StackTrace? stackTrace]) {
    _instance.log(Level.error, message, "E/PRETTY_LOGGER${tag==null?"":" [$tag] "}", stackTrace);
  }



  /// 核心日志打印方法
  /// level: 日志等级
  /// message: 日志内容
  /// tag: 日志标签
  /// stackTrace: 堆栈信息
  /// 默认tag为PRETTY_LOGGER
  /// 默认堆栈信息为空
  /// 默认日志等级为debug
  /// 默认日志输出为控制台
  /// dynamic类型可以是任意类型，会根据类型进行转换成字符串
  void log(Level level, dynamic message, dynamic tag, StackTrace? stackTrace){
    var logEvent = LogEvent(level, message, tag, stackTrace);
    if(_loggable){
      /// 这路的_printer是LogPrinter还是PrettyPrinter？
      /// LogPrinter是抽象类，PrettyPrinter是LogPrinter的子类
      /// 通过_printer.log()方法将LogEvent对象转换成字符串数组
      /// 通过_output.output()方法将字符串数组输出到控制台
      /// 输出的日志会根据日志等级进行过滤
      var output = _printer.log(logEvent);
      if(output.isNotEmpty){
        var outputEvent = OutputEvent(level, output);
        _output.output(outputEvent);
      }
    }
  }


  void destroy(){
    _output.destroy();
    _printer.destroy();
  }

  /// 使用示例:
  /// 
  /// // 只输出到控制台
  /// Logger.getInstance(output: ConsoleOutput());
  /// 
  /// // 只输出到文件
  /// Logger.getInstance(output: FileOutput());
  /// 
  /// // 同时输出到控制台和文件
  /// Logger.getInstance(output: MultiOutput([ConsoleOutput(), FileOutput()]));



}